package com.lzx.RandomForest;

import com.lzx.utils.GetMap;
import com.lzx.reader.ReadFile;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author: 如寄
 * @version: v1.0
 * @description: com.新闻分类.RandomForest
 * @date:2021/5/20
 */
public class RandomForestClassification {
    private GetMap getMap = new GetMap();
    private int inx = 0;
    private List<TreeNode> forest = null;

    /**
     *
     * @param model:模型
     * @throws IOException
     */
    public RandomForestClassification(File model) throws IOException {
        forest = getForest(model);
    }

    /**
     *
     * 读取模型、生成决策树
     *
     */
    private List<TreeNode> getForest(File model) throws IOException {
        List<String> tree = ReadFile.read(model);
        List<TreeNode> treeNodes = new ArrayList<>();
        for (String s : tree) {
            TreeNode treeNode = buildTree(s.split(" "));
            treeNodes.add(treeNode);
            inx = 0;
        }
        return treeNodes;
    }

    /**
     *
     * @param content :新闻内容
     * @param num :森林中树的数量
     * @return : 分类结果
     * @throws IOException
     */
    public String ClassificationNew(String content, int num) throws IOException {
        Map<String, Boolean> map = getMap.toMap(content);
        Map<String, Integer> typeMap = new HashMap<>();
        for (int i = 0; i < num; i++) {
            String type = dfs(forest.get(i), map);
            if (typeMap.containsKey(type)) {
                typeMap.replace(type, typeMap.get(type) + 1);
            } else typeMap.put(type, 1);
        }
        //bagging投票
        int temp = 0;
        String type = null;
        for (Map.Entry<String, Integer> entry : typeMap.entrySet()) {
            if (entry.getValue() >= temp) {
                type = entry.getKey();
                temp = entry.getValue();
            }
        }
        return type;
    }

    /**
     *
     * @param tree :前序遍历的决策树
     * @return 一棵决策树
     */
    private TreeNode buildTree(String[] tree) {
        if (tree[inx].equals("#")) {
            inx++;
            return null;
        }
        TreeNode index = new TreeNode(tree[inx++]);
        index.left = buildTree(tree);
        index.right = buildTree(tree);
        return index;
    }

    /**
     *
     * @param index : 一棵决策树
     * @param map :经分词处理的数据
     * @return :分类结果
     */
    private String dfs(TreeNode index, Map<String, Boolean> map) {
        if (index.right == null && index.left == null)
            return index.node;
        if (map.containsKey(index.node)) {
            return dfs(index.left, map);
        }
        return dfs(index.right, map);
    }

}
